//
//  TLSoundPlayer.m
//  KidReading
//
//  Created by telen on 14/12/29.
//  Copyright (c) 2014年 刘赞黄Telen. All rights reserved.
//

#import "TLSoundPlayer.h"

#import "ConstDefine.h"

static TLSoundPlayer* tlsoundplayerSingle = nil;

@implementation TLSoundPlayer

- (instancetype)init
{
    if (self = [super init]) {
        playDict = [[NSMutableDictionary alloc] initWithCapacity:0];
        playArrDict = [[NSMutableDictionary alloc] initWithCapacity:0];
    }
    return self;
}

+ (TLSoundPlayer *)shareSingle
{
    if (!tlsoundplayerSingle) {
        tlsoundplayerSingle = [[TLSoundPlayer alloc] init];
    }
    return tlsoundplayerSingle;
}

- (BOOL)prepareToPlayFile:(NSString *)fileFullPath fromTime:(NSTimeInterval)ftime
{
    BOOL ret = YES;
    if (![playDict objectForKey:fileFullPath]) {
        NSURL* playURL = [NSURL fileURLWithPath:fileFullPath];
        NSError* playSetError = nil;
        AVAudioPlayer* audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:playURL error:&playSetError];
        if (!audioPlayer) {
            NSLog(@"error:%@",playSetError);
            return NO;
        }
        [audioPlayer setCurrentTime:ftime];
        ret = [audioPlayer prepareToPlay];
        if (ret) {
            audioPlayer.delegate = self;
            [playDict setObject:audioPlayer forKey:fileFullPath];
        }
    }
    return ret;
}

- (BOOL)prepareToPlayFile:(NSString *)fileFullPath andDelegate:(id<TLSoundPlayerDelegate>)delegate
{
    BOOL ret = YES;
    if (![playDict objectForKey:fileFullPath]) {
        NSURL* playURL = [NSURL fileURLWithPath:fileFullPath];
        NSError* playSetError = nil;
        AVAudioPlayer* audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:playURL error:&playSetError];
        if (!audioPlayer) {
            NSLog(@"error:%@",playSetError);
            return NO;
        }
        ret = [audioPlayer prepareToPlay];
        if (ret) {
            audioPlayer.delegate = self;
            [playDict setObject:audioPlayer forKey:fileFullPath];
            if (delegate) {
                NSValue* value = [NSValue valueWithNonretainedObject:delegate];
                [playDict setObject:value forKey:[fileFullPath stringByAppendingString:@"_"]];
            }
        }
    }
    return ret;
}

- (BOOL)playFile:(NSString *)fileFullPath andDelegate:(id<TLSoundPlayerDelegate>)delegate
{
    BOOL ret = YES;
    AVAudioPlayer* audioPlayer = [playDict objectForKey:fileFullPath];
    if (!audioPlayer) {
        [self prepareToPlayFile:fileFullPath fromTime:audioPlayer.currentTime];
        audioPlayer = [playDict objectForKey:fileFullPath];
    }else{
        id<TLSoundPlayerDelegate> delegate_ = [[playDict objectForKey:[fileFullPath stringByAppendingString:@"_"]] nonretainedObjectValue];
        if (delegate != delegate_) {
            return  NO;
        }
    }
    audioPlayer.delegate = self;
    ret = [audioPlayer play];
    if (ret && delegate) {
        NSValue* value = [NSValue valueWithNonretainedObject:delegate];
        [playDict setObject:value forKey:[fileFullPath stringByAppendingString:@"_"]];
    }
    return ret;
}

- (BOOL)rePlayFile:(NSString *)fileFullPath andDelegate:(id<TLSoundPlayerDelegate>)delegate
{
    BOOL ret = YES;
    AVAudioPlayer* audioPlayer = [playDict objectForKey:fileFullPath];
    if (!audioPlayer) {
        [self prepareToPlayFile:fileFullPath fromTime:0];
        audioPlayer = [playDict objectForKey:fileFullPath];
    }else{
        id<TLSoundPlayerDelegate> delegate_ = [[playDict objectForKey:[fileFullPath stringByAppendingString:@"_"]] nonretainedObjectValue];
        if (delegate != delegate_) {
            return  NO;
        }
    }
    audioPlayer.delegate = self;
    [audioPlayer stop];
    [audioPlayer setCurrentTime:0];
    [audioPlayer prepareToPlay];
    NSTimeInterval playbackDelay = 0.3;              // must be ≥ 0
    ret = [audioPlayer playAtTime:audioPlayer.deviceCurrentTime + playbackDelay];
    if (ret && delegate) {
        NSValue* value = [NSValue valueWithNonretainedObject:delegate];
        [playDict setObject:value forKey:[fileFullPath stringByAppendingString:@"_"]];
    }
    return ret;
}

- (BOOL)playFile:(NSString *)fileFullPath fromTime:(NSTimeInterval)ftime andDelegate:(id<TLSoundPlayerDelegate>)delegate
{
    BOOL ret = YES;
    AVAudioPlayer* audioPlayer = [playDict objectForKey:fileFullPath];
    if (!audioPlayer) {
        [self prepareToPlayFile:fileFullPath fromTime:ftime];
        audioPlayer = [playDict objectForKey:fileFullPath];
    }else{
        id<TLSoundPlayerDelegate> delegate_ = [[playDict objectForKey:[fileFullPath stringByAppendingString:@"_"]] nonretainedObjectValue];
        if (delegate != delegate_) {
            return  NO;
        }
    }
    audioPlayer.delegate = self;
    ret = [audioPlayer play];
    if (ret && delegate) {
        NSValue* value = [NSValue valueWithNonretainedObject:delegate];
        [playDict setObject:value forKey:[fileFullPath stringByAppendingString:@"_"]];
    }
    return ret;
}

- (BOOL)stopFilePlay:(NSString *)fileFullPath
{
    BOOL ret = YES;
    AVAudioPlayer* audioPlayer = [playDict objectForKey:fileFullPath];
    if (audioPlayer && [audioPlayer isKindOfClass:AVAudioPlayer.class]) {
        NSString* key = fileFullPath;
        id<TLSoundPlayerDelegate> delegate = [[playDict objectForKey:[key stringByAppendingString:@"_"]] nonretainedObjectValue];
        if (delegate && [delegate respondsToSelector:@selector(tlSoundActionToStop_PlayingFile:)]) {
            [delegate tlSoundActionToStop_PlayingFile:key];
        }
        [audioPlayer stop];
    }
    return ret;
}

- (BOOL)stopFilePlay_andClean:(NSString *)fileFullPath
{
    BOOL ret = YES;
    ret = [self stopFilePlay:fileFullPath];
    [playDict removeObjectForKey:fileFullPath];
    [playDict removeObjectForKey:[fileFullPath stringByAppendingString:@"_"]];
    return ret;
}

- (void)stopAllFiles
{
    NSArray* allkeys = [playDict allKeys];
    for (NSString* key in allkeys) {
        if(key.length==0)continue;
        [self stopFilePlay:key];
    }
    //停止 短词
    allkeys = [playArrDict allKeys];
    for (NSString* key in allkeys) {
        if(key.length==0)continue;
        AVAudioPlayer* audioPlayer = [playArrDict objectForKey:key];
        if (audioPlayer && [audioPlayer isKindOfClass:AVAudioPlayer.class]) {
            [audioPlayer stop];
        }
    }
}

- (void)stopAllFiles_andClean
{
    [self stopAllFiles];
    [playDict removeAllObjects];
    [playArrDict removeAllObjects];
    playArr = nil;
}

- (BOOL)isFilePlaying:(NSString *)fileFullPath
{
    BOOL ret = NO;
    AVAudioPlayer* audioPlayer = [playDict objectForKey:fileFullPath];
    if (audioPlayer) {
        return audioPlayer.isPlaying;
    }
    return ret;
}

- (NSTimeInterval)getPlayProgressForFile:(NSString *)fileFullPath
{
    AVAudioPlayer* audioPlayer = [playDict objectForKey:fileFullPath];
    if (audioPlayer) {
//        NSLog(@"%lf",audioPlayer.currentTime*1000);
        return audioPlayer.currentTime*1000;
    }
    return 0;
}

- (AVAudioPlayer *)getAudioPlayerForPlayFile:(NSString *)fileFullPath
{
    return [playDict objectForKey:fileFullPath];
}

//独立的词组播放api
- (void)playSoundArr:(NSArray *)fullPathArr andDelegate:(id<TLSoundPlayerDelegate>)delegate withSign:(NSString*)sign
{
    //停止
    NSArray* allkeys = [playArrDict allKeys];
    for (NSString* key in allkeys) {
        if(key.length==0)continue;
        AVAudioPlayer* audioPlayer = [playArrDict objectForKey:key];
        if (audioPlayer && [audioPlayer isKindOfClass:AVAudioPlayer.class]) {
            [audioPlayer stop];
        }
    }
    [playArrDict removeAllObjects];
    //
    playArr = fullPathArr;
    BOOL ret = YES;
    for (int i =0; i<playArr.count; i++) {
        NSString* fileFullPath = [playArr objectAtIndex:i];
        NSURL* playURL = [NSURL fileURLWithPath:fileFullPath];
        NSError* playSetError = nil;
        AVAudioPlayer* audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:playURL error:&playSetError];
        if (!audioPlayer) {
            NSLog(@"error:%@",playSetError);
#if __Debug_playError
            NSString* str = [NSString stringWithFormat:@"%@\n\n%@",fileFullPath,playSetError];
            [[[UIAlertView alloc] initWithTitle:@"播放打开error" message:str delegate:nil cancelButtonTitle:@"关闭close" otherButtonTitles:nil] show];
#endif
        }
        ret = [audioPlayer prepareToPlay];
        audioPlayer.delegate = self;
        if (ret) {
            [playArrDict setObject:audioPlayer forKey:[NSString stringWithFormat:@"%@_%d",fileFullPath,i]];
        }else{
            break;
        }
    }
    if (!ret) {
        [playArrDict removeAllObjects];
        playArr = nil;
    }
    NSValue* value = [NSValue valueWithNonretainedObject:delegate];
    [playArrDict setObject:value forKey:[NSString stringWithFormat:@"%d",(int)playArr]];
    if(sign)[playArrDict setObject:sign forKey:@"sign"];
    NSString* playPath = [NSString stringWithFormat:@"%@_%d",[playArr objectAtIndex:0],0];
    ret = [((AVAudioPlayer*)[playArrDict objectForKey:playPath]) play];
    if (ret) {
        if (delegate && [delegate respondsToSelector:@selector(tlSoundPlayerDidStartPlayingArr:withSign:)]) {
            [delegate tlSoundPlayerDidStartPlayingArr:playArr withSign:sign];
        }
    }
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    NSArray* allkeys = [playDict allKeys];
    for (NSString* key in allkeys) {
        if(key.length==0)continue;
        if([playDict objectForKey:key] == player){
            id<TLSoundPlayerDelegate> delegate = [[playDict objectForKey:[key stringByAppendingString:@"_"]] nonretainedObjectValue];
            if (delegate && [delegate respondsToSelector:@selector(tlSoundPlayerDidFinishPlayingFile:)]) {
                [delegate tlSoundPlayerDidFinishPlayingFile:key];
            }
            if (delegate && [delegate respondsToSelector:@selector(tlSoundPlayerDidFinishPlayingFile:player:)]) {
                [delegate tlSoundPlayerDidFinishPlayingFile:key player:player];
            }
        }
    }
    //词组发音
    NSInteger count = playArr.count;
    if(count)
        for (int i =0; i<count; i++) {
            NSString* key = [NSString stringWithFormat:@"%@_%d",[playArr objectAtIndex:i],i];
            if([playArrDict objectForKey:key] == player){
                if (i+1 <count) {
                    NSString* playPath = [NSString stringWithFormat:@"%@_%d",[playArr objectAtIndex:1+i],1+i];
                    [((AVAudioPlayer*)[playArrDict objectForKey:playPath]) play];
                }else{
                    id<TLSoundPlayerDelegate> delegate = [[playArrDict objectForKey:[NSString stringWithFormat:@"%d",(int)playArr]] nonretainedObjectValue];
                    if (delegate && [delegate respondsToSelector:@selector(tlSoundPlayerDidFinishPlayingArr:withSign:)]) {
                        NSString* sign = [playArrDict objectForKey:@"sign"];
                        [delegate tlSoundPlayerDidFinishPlayingArr:playArr withSign:sign];
                    }
                    [playArrDict removeAllObjects];
                    playArr = nil;
                }
            }
        }
}

- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
    NSLog(@"播放解码错误 %@",error);
#if __Debug_playError
    NSString* str = [NSString stringWithFormat:@"%@\n\n%@",player.url,error];
    [[[UIAlertView alloc] initWithTitle:@"播放解码error" message:str delegate:nil cancelButtonTitle:@"关闭close" otherButtonTitles:nil] show];
#endif
    //词组发音
    NSInteger count = playArr.count;
    if(count)
        for (int i =0; i<count; i++) {
            NSString* key = [NSString stringWithFormat:@"%@_%d",[playArr objectAtIndex:i],i];
            if([playArrDict objectForKey:key] == player){
                id<TLSoundPlayerDelegate> delegate = [[playArrDict objectForKey:[NSString stringWithFormat:@"%d",(int)playArr]] nonretainedObjectValue];
                if (delegate && [delegate respondsToSelector:@selector(tlSoundPlayerDidFinishPlayingArr:withSign:)]) {
                    NSString* sign = [playArrDict objectForKey:@"sign"];
                    [delegate tlSoundPlayerDidFinishPlayingArr:playArr withSign:sign];
                }
                [playArrDict removeAllObjects];
                playArr = nil;
            }
        }
}

@end
